Keygen Tutorial 3 Yes123 '99 ---[ WARNING ]-------------------------------------------------------------------------------- This Tutorial is for education purpose only. I wrote it to allow you to understand how are coded some protections schemes in software. I didn't make it to allow you to use the target program without paying the author. If you plan to use these programs regularly, please remeber to send your $ to the authors, don't be a outlaw, and over all, don't be a LAMER !!! ---[ INTRO ]---------------------------------------------------------------------------------- target: Screen Loupe for Window95/NT v4.4 where : http://www.execpc.com/~sbd Tools : SoftIce for Win9x v3.24 W32Dasm v8.9 Programming Language (C, Pascal, asm, anyone you want, I'll use our old C) This is my third tutorial in english. I hope my bad spelling won't make this text too much hard to understand for you. :) I'll try to teach you how to make a key generator for a program. The way i teach will be based more on reverse enginerring (instead of only cracking the program, we try to fully understand the whole key-generating algorithm), some newbies maybe having problem of reading this. The protection scheme actually encode your name into certain format, and compare with two possible encoded name, if it match it will register you directly without further checking on your company and registration key. If it doesn't match then it will perform key-generating process and compare the generated key with your fake key. By reading the above paragraph, i think you should know there are many ways to crack this program(byte patching, look at real key directly, reverse the code to find that two built-in name...), but what i'm teaching here is the key-generator process so we are only interested in building a key-generator.(but i'll still touch a bit on others method :)) If you want to unregister the program, delete the all keys in registry: [HKEY_USERS\.Default\Software\Software by Design\Screen Loupe for Windows 95/NT\Registration] I'll assume you know the following: - basic use of SoftIce - asm instructions (at least the ones used for cracking) - knowing which call is important call ---[ TUTORIAL ]------------------------------------------------------------------------------- At first, launch SoftICe (assuming you know the basics, and how to setup this Numega's nice tool). Then launch our target, loupe.exe! Go to the help menu and select the register. Enter a name and company. Simplily put a breakpoint before you press ok(eg.bpx hmemcpy or others...).You should have break into softice after pressing OK button. Keep pressing F12 until you get back to the traget program code. You will be in: * Reference To: USER32.GetDlgItemTextA, Ord:0104h | :004060FB 8B1D6C824100 mov ebx, dword ptr [0041826C] ;ebx is function GetDlgItemTextA :00406101 57 push edi :00406102 6A32 push 00000032 :00406104 56 push esi :00406105 6A65 push 00000065 :00406107 55 push ebp :00406108 FFD3 call ebx ;call to get our name :0040610A 8D7E32 lea edi, dword ptr [esi+32] :0040610D 6A32 push 00000032 :0040610F 57 push edi :00406110 6A66 push 00000066 :00406112 55 push ebp :00406113 FFD3 call ebx ;call to get our company :00406115 8D442410 lea eax, dword ptr [esp+10] :00406119 6800010000 push 00000100 :0040611E 50 push eax * Possible Ref to Menu: MenuID_03E8, Item: "System Information Ctrl+S" | :0040611F 6A67 push 00000067 :00406121 55 push ebp :00406122 FFD3 call ebx ;call to get our fake key :00406124 8D4C2410 lea ecx, dword ptr [esp+10] Until here you should have notice that the program use function GetDlgItemTextA to get our name, company and registration key. It move the function into ebx first, then call the function using 'call ebx' for 3 times. When you reach here, by typing d ecx you should see your fake registration key. :00406128 51 push ecx ;ecx=our fake key :00406129 E83D9B0000 call 0040FC6B The is a call that covert our our fake key from string form into hexadecimal format. The converted result be in eax.(The registartion key can only takes in digits.) :0040612E 56 push esi ;esi=our name :0040612F 8BD8 mov ebx, eax ;move the result to ebx :00406131 E8FA7C0000 call 0040DE30 ;call that encode our name :00406136 83C408 add esp, 00000008 :00406139 3D92A71901 cmp eax, 0119A792 ;compare encoded name with 119A792 :0040613E 7518 jne 00406158 The call at line 406131 is very important, it has being call 3 times in this program. It is used to encode the data pushed in into certain format and return the result at eax. In the above case, it encode our name and compare it with 119A792(certain encoded name). If it is equal, then it will register you as the author "Grgory Braun" with correct registration key. The following code is registering you as "Gregory Braun" with company name"Software Design", (we neglect them here...) ....... * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040613E(C) | :00406158 3D3CCE5F0D cmp eax, 0D5FCE3C ;compare our encoded name with 0D5FCE3C :0040615D 750C jne 0040616B If you want to do a byte-patching, then 40615D is a good place to patch, change the 750C into 9090, so that it can always go to 40615F. * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00406156(U) | :0040615F 57 push edi ;edi=our company :00406160 56 push esi ;esi=our name :00406161 E85A770000 call 0040D8C0 ;calculate real key :00406166 83C408 add esp, 00000008 :00406169 8BD8 mov ebx, eax ;real key to ebx If our decoded name equal to either 119A792 or 0D5FCE3C, then it will goes to address 40615F. From 40615F to 406169, it call the code generating function and put the result into ebx, ebx originally is our fake key that uses to compare with the encoded result. * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040615D(C) | :0040616B 57 push edi ;edi=our company :0040616C 56 push esi ;esi=our name :0040616D E84E770000 call 0040D8C0 ;call that calculate real key :00406172 83C408 add esp, 00000008 ;stack correction :00406175 3BD8 cmp ebx, eax ;compare our key to real key :00406177 5F pop edi :00406178 741D je 00406197 ;jump to success message :0040617A 68CFEA0000 push 0000EACF ;error message * Possible Reference to String Resource ID=05000: " Register Screen Loupe for Windows 95/NT" If our didn't jump over the code in 40615F-406169, then the ebx=eax and we can jump over error message. Look carefully at 406161 and 40616D, they are calling the same function, this is the function that we are interested in.(in 406169, it move the result in ebx, so that ebx always equal to eax, if we jump over those code, then ebx is still our fake key). If you want to just any want to look for the real key then type '? eax' after after the call at 40616D. The positive decimal number will be our real registration key. In order to make a key-generator we trace into 'call 0040D8C0': * Referenced by a CALL at Addresses: |:004058CD , :00405FA3 , :00406161 , :0040616D | :0040D8C0 8B442404 mov eax, dword ptr [esp+04] ;eax=name :0040D8C4 56 push esi :0040D8C5 8B35E8F54100 mov esi, dword ptr [0041F5E8] ;esi=ABED0F00 :0040D8CB 50 push eax :0040D8CC 81CE78030000 or esi, 00000378 ;esi=ABED0F00 or 378=ABED0F78 :0040D8D2 E859050000 call 0040DE30 ;call that encode our name :0040D8D7 8B4C2410 mov ecx, dword ptr [esp+10] ;ecx=company :0040D8DB 03F0 add esi, eax ;esi=esi+eax :0040D8DD 51 push ecx ;push company :0040D8DE E84D050000 call 0040DE30 ;call that encode our company :0040D8E3 83C408 add esp, 00000008 ;stack correction :0040D8E6 03C6 add eax, esi ;eax=eax(encoded company)+esi :0040D8E8 5E pop esi :0040D8E9 C3 ret The above code basically very short and simple, the encode our name and company name using 'call 0040DE30' and add them together with ABEDOF78. It can be summarized as follow: Real key = [encoded name] + [encode company] + ABEDOF78 If we noticed carefully the 'call 0040DE30' is called befero this at 406131, at that times it is used to encode our name. Since it is the most important call, we trace into 'call 0040DE30': * Referenced by a CALL at Addresses: |:00406131 , :0040D8D2 , :0040D8DE | :0040DE30 51 push ecx :0040DE31 53 push ebx :0040DE32 8B5C240C mov ebx, dword ptr [esp+0C] ;ebx=value pushed in.(name/comp) :0040DE36 56 push esi :0040DE37 33F6 xor esi, esi ;esi=0 :0040DE39 53 push ebx :0040DE3A 8974240C mov dword ptr [esp+0C], esi ;clear [esp+0c]=place to store ;our encoded result * Reference To: KERNEL32.lstrlenA, Ord:0308h | :0040DE3E FF153C814100 Call dword ptr [0041813C] ;get length of ebx, eax=result :0040DE44 85DB test ebx, ebx :0040DE46 744F je 0040DE97 ;jump if no name/company enter :0040DE48 85C0 test eax, eax :0040DE4A 744B je 0040DE97 ;jump if length = 0 :0040DE4C 33D2 xor edx, edx ;clear edx,edx is counter :0040DE4E 85C0 test eax, eax :0040DE50 7E45 jle 0040DE97 ;jump if length = 0 :0040DE52 55 push ebp :0040DE53 57 push edi * Possible StringData Ref from Data Obj ->"|b!pz*ls;rn|lf$vi^Axpe)rx5aic&9/2m5lsi4@0dmZw9" ->"4cmqpfhw" | :0040DE54 BE10C74100 mov esi, 0041C710 ;esi=417C710,a place with random no. [41C710] strore a lot of random number that is important in key-generating. by typing d esi you will see: XXXX:0041C710 72 62 21 70 7A 2A 6C 73-3B 72 6E 7C 6C 66 24 76 XXXX:0041C720 69 5E 41 78 70 65 29 72-78 35 61 69 63 .... It is very important, please write them down if you want to make a keygen. :0040DE59 BF01000000 mov edi, 00000001 ;edi is also act as counter :0040DE5E 2BF3 sub esi, ebx ;esi=esi-ebx :0040DE60 8BCB mov ecx, ebx ;ecx=ebx :0040DE62 2BFB sub edi, ebx ;edi=edi-ebx * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040DE8D(C) | :0040DE64 0FBE1C0E movsx ebx, byte ptr [esi+ecx] ;ebx=[41C710+edx] :0040DE68 0FBEAC10D8C64100 movsx ebp, byte ptr [eax+edx+0041C6D8];ebp=[41C6D8+edx+eax] [41C6D8] also a set of random number that are very important. By typing 'd 41C6D8', you see: XXXX:41C6D8 23 73 65 72 42 26 6E 7A-7C 6D 66 4D 31 2F 35 28 XXXX:41C6E8 21 73 64 24 4D 71 2E 7B-73 5D 2B 73 46 6A 74 4B ..... Please write them down also if you want to make a keygen. :0040DE70 0FAFDD imul ebx, ebp ;ebx=ebx*ebp :0040DE73 8D2C0F lea ebp, dword ptr [edi+ecx] ;ebp=edx+1 :0040DE76 0FAFDD imul ebx, ebp ;ebx=ebx*(edx+1) :0040DE79 0FBE29 movsx ebp, byte ptr [ecx] ;ebp=one byte from name/company :0040DE7C 0FAFDD imul ebx, ebp ;ebx=ebx*ebp :0040DE7F 8B6C2410 mov ebp, dword ptr [esp+10] ;ebp=[esp+10] :0040DE83 03EB add ebp, ebx ;ebp=ebp*ebx :0040DE85 42 inc edx ;increase counter :0040DE86 41 inc ecx ;increase address of name/comp :0040DE87 3BD0 cmp edx, eax ;comapre counter with length :0040DE89 896C2410 mov dword ptr [esp+10], ebp ;move result to [esp+10] :0040DE8D 7CD5 jl 0040DE64 ;jump if counter#include int count1; char ran1[20]={0x7c,0x62,0x21,0x70,0x7a,0x2a,0x6c,0x73,0x3b,0x72,0x6e,0x7c,0x6c,0x66,0x24,0x76,0x69,0x5e,0x41,0x78}; char ran2[20]={0x23,0x73,0x65,0x72,0x42,0x26,0x6e,0x7a,0x7c,0x6d,0x66,0x4d,0x31,0x2f,0x35,0x28,0x21,0x73,0x64,0x24}; long encode(char [],int); //call that similar to 'call 40DE30' int main(void) { long code=0xabed0f78; //the esi result in line 40D8CC int length; char name[20],comp[20]; clrscr(); textcolor(14); cprintf(" __,__\r\n"); cprintf(" / \\\r\n" ); cprintf(" vvvvvvv /|__/|\r\n"); cprintf(" I /O,O |\r\n"); cprintf(" I /_____ | /|/|\r\n"); cprintf(" J|/^ ^ ^ \\ | /00 | _//|\r\n"); cprintf(" |^ ^ ^ ^ |W| |/^^\\ | /oo |\r\n"); cprintf(" \\m___m__|_| \\m_m_| \\mm_|\r\n"); textcolor(10); cprintf("==================================================="); textcolor(11); cprintf("\r\nKeyGenerator - Screen Loupe for Windows95/NT v4.4"); textcolor(10); cprintf("\r\n==================================================="); printf("\nCracked by "); textcolor(14); cprintf("%c%c%c",0x10,0x10,0x10); textcolor(12); cprintf("Yes123"); textcolor(14); cprintf("%c%c%c",0x11,0x11,0x11); printf(" - March 1999"); printf("\n\nEnter register name (1-20 chars)= "); //it can be more if you use more value scanf("%[^\n]",name); //of [41C710],i used only 20. getchar(); printf("Enter register company (1-10 chars)= "); //it can be more if you use more value scanf("%[^\n]",comp); //of [41C6D8], i used only 20. for (length=0;name[length]>0;length++); //calculate length of our name code=code+encode(&name,length); for (length=0;comp[length]>0;length++); //calculate length of our company name code=code+encode(&comp,length); printf("Your registration key = %lu",code); return ; } long encode(char code[],int length){ //same as 'call 40DE30' long key=0,result=0; for (count1=0;code[count1]>0;count1++){ key=ran1[count1]; key=key*ran2[count1+length]; key=key*(count1+1); key=key*code[count1]; result=result+key; } return result; } ---[ LAST ]-------------------------------------------------------------------------------------- I know my english expressing ability is weak, so in many place i know what's happening but i cann't express well or explain to you clearly. I hope you can really try it out then you can understand more out of it. You can also try to reverse encoded name of 119A792 or 0D5FCE3C, see what name correspound to this value. It should have many possibility(like UNIX password), but you can try it out to improve your reverse enginering skill. Thanks for reading my keygen tutorial. ---[ THAT'S ALL FOLKS ]----------------------------------------------------------------------- __,__ / \ vvvvvvv /|__/| I /O,O | I /_____ | J|/^ ^ ^ \ | |^ ^ ^ ^ |W| \m___m__|_|Yes123 '99